package com.huohuzhihui.oa.service.impl;

import com.huohuzhihui.common.exception.CustomException;
import com.huohuzhihui.common.utils.DateUtils;
import com.huohuzhihui.common.utils.SecurityUtils;
import com.huohuzhihui.oa.domain.OaDocument;
import com.huohuzhihui.oa.domain.OaFlowProcess;
import com.huohuzhihui.oa.domain.OaFlowStep;
import com.huohuzhihui.oa.mapper.OaDocumentMapper;
import com.huohuzhihui.oa.mapper.OaFlowProcessMapper;
import com.huohuzhihui.oa.mapper.OaFlowStepMapper;
import com.huohuzhihui.oa.service.IOaFlowProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;

/**
 * 工作流步骤Service业务层处理
 * 
 * @author yepanpan
 * @date 2020-12-08
 */
@Service
public class OaFlowProcessServiceImpl implements IOaFlowProcessService 
{
    @Autowired
    private OaFlowProcessMapper oaFlowProcessMapper;
    @Autowired
    private OaFlowStepMapper oaFlowStepMapper;
    @Autowired
    private OaDocumentMapper oaDocumentMapper;

    /**
     * 查询工作流步骤
     * 
     * @param id 工作流步骤ID
     * @return 工作流步骤
     */
    @Override
    public OaFlowProcess selectOaFlowProcessById(Long id)
    {
        return oaFlowProcessMapper.selectOaFlowProcessById(id);
    }

    /**
     * 查询工作流步骤列表
     * 
     * @param oaFlowProcess 工作流步骤
     * @return 工作流步骤
     */
    @Override
    public List<OaFlowProcess> selectOaFlowProcessList(OaFlowProcess oaFlowProcess)
    {
        return oaFlowProcessMapper.selectOaFlowProcessList(oaFlowProcess);
    }

    /**
     * 新增工作流步骤
     * 
     * @param oaFlowProcess 工作流步骤
     * @return 结果
     */
    @Override
    public int insertOaFlowProcess(OaFlowProcess oaFlowProcess)
    {
        return oaFlowProcessMapper.insertOaFlowProcess(oaFlowProcess);
    }

    /**
     * 修改工作流步骤
     * 
     * @param oaFlowProcess 工作流步骤
     * @return 结果
     */
    @Override
    @Transactional
    public int updateOaFlowProcess(OaFlowProcess oaFlowProcess)
    {
    	OaFlowProcess old = oaFlowProcessMapper.selectOaFlowProcessById(oaFlowProcess.getId());
    	OaDocument doc = oaDocumentMapper.selectOaDocumentById(old.getDocumentId());
    	if("4".equals(oaFlowProcess.getStatus())) { //退回
    		doc.setStatus("4");
    	}else if("3".equals(oaFlowProcess.getStatus())) { //通过
    		OaFlowStep step = oaFlowStepMapper.selectOaFlowStepById(old.getStepId());
    		if("9".equals(step.getType())) {//终结
    			doc.setStatus("9");
    			doc.setStepId(0l);
    		}else {//下一流程
    			boolean pass = true;
    			if("3".equals(step.getType())) {//会审
    				OaFlowProcess fpc = new OaFlowProcess();
    		    	fpc.setDocumentId(oaFlowProcess.getDocumentId());
    		    	fpc.setStepId(old.getStepId());    	
    		    	List<OaFlowProcess> list = selectOaFlowProcessList(fpc);
    		    	for(OaFlowProcess p : list) {
    		    		if(!"3".equals(p.getStatus())) {//有未通通过的处理
    		    			pass = false;
    		    			break;
    		    		}
    		    	}
    			}
    			
    			if(pass) {
    				OaFlowStep scond = new OaFlowStep();
            		scond.setPid(step.getId());
            		List<OaFlowStep> list = oaFlowStepMapper.selectOaFlowStepList(scond);
            		if(list == null || list.size() == 0) {
            			throw new CustomException("流程配置有误");
            		}
            		step = list.get(0);
        			doc.setStepId(step.getId());
        			processStep(doc, step);
    			}        		
    		}
    	}
    	doc.setUpdateTime(DateUtils.getNowDate());
    	oaDocumentMapper.updateOaDocument(doc);
        oaFlowProcess.setUpdateTime(DateUtils.getNowDate());
        return oaFlowProcessMapper.updateOaFlowProcess(oaFlowProcess);
    }

    /**
     * 批量删除工作流步骤
     * 
     * @param ids 需要删除的工作流步骤ID
     * @return 结果
     */
    @Override
    public int deleteOaFlowProcessByIds(Long[] ids)
    {
        return oaFlowProcessMapper.deleteOaFlowProcessByIds(ids);
    }

    /**
     * 删除工作流步骤信息
     * 
     * @param id 工作流步骤ID
     * @return 结果
     */
    @Override
    public int deleteOaFlowProcessById(Long id)
    {
        return oaFlowProcessMapper.deleteOaFlowProcessById(id);
    }


    /**
     * 查询公文对应指定步骤可操作的用户列表
     * 
     * @param document OaDocument 公文
     * @param step OaFlowStep 工作流步骤
     * @return 结果
     */
    @Override
    public Set<Long> selectStepUser(OaDocument document, OaFlowStep step){
    	String rule = step.getRule();
    	String sql = "";

    	if("1".equals(rule)) {//1=部门领导	
    		sql = "select u.user_id from sys_user u"
    				+ " join sys_user_role ur on u.user_id=ur.user_id"
    				+ " join sys_role r on r.role_id=ur.role_id and r.role_key='dept'"
    				+ " where u.dept_id = (select dept_id from sys_user u2 where u2.user_id=SENDER)";
    	}else if("2".equals(rule)){ //2=上级部门领导	
    		sql = "select u.user_id from sys_user u"
    				+ " join sys_user_role ur on u.user_id=ur.user_id"
    				+ " join sys_role r on r.role_id=ur.role_id and r.role_key='dept'"
    				+ " where u.dept_id = (select dept_id from sys_user u2 where u2.user_id=ME)";
    	}else if("3".equals(rule)){ //3=指定人	
    		String ps = step.getParam().replace(",", "','");
    		sql = "select user_id from sys_user where user_name in ('"+ps+"') OR nick_name in ('"+ps+"')";
    	}else if("4".equals(rule)){ //4=指定部门	
    		String ps = step.getParam().replace(",", "','");
    		sql = "select user_id from sys_user where dept_id in (select dept_id from sys_dept where dept_name in ('"+ps+"') )";
    	}else if("5".equals(rule)){ //5=指定角色	
    		String ps = step.getParam().replace(",", "','");
    		sql = "select u.user_id from sys_user u"
    				+ " join sys_user_role ur on u.user_id=ur.user_id"
    				+ " join sys_role r on r.role_id=ur.role_id"
    				+ " where r.role_name in ('"+ps+"') ";
    	}else{ //9=自定义
    		sql = step.getParam();
    	}
    	sql = sql.replaceAll("SENDER", ""+document.getAddUser());
    	sql = sql.replaceAll("ME", ""+SecurityUtils.getLoginUser().getUser().getUserId());
    	return oaFlowProcessMapper.selectStepUsers(sql);
    }
    
    
    /**
     * 处理一步流程
     * @param oaDocument
     * @return
     */
    public int processStep(OaDocument document, OaFlowStep step) {
    	int count = 0;
    	Set<Long> users = selectStepUser(document, step);
    	if("1".equals(step.getType())) {//判断是否有处理权限
    		if(!users.contains(document.getAddUser())) {
    			throw new CustomException("您没有权限");
    		}
    		document.setStepId(step.getId());
    		OaFlowStep scond = new OaFlowStep();
    		scond.setPid(step.getId());
    		List<OaFlowStep> list = oaFlowStepMapper.selectOaFlowStepList(scond);
    		if(list == null || list.size() == 0) {
    			throw new CustomException("流程配置有误");
    		}
    		step = list.get(0);
    		document.setStepId(step.getId());
    		document.setStatus("1");
    		count += processStep(document, step);
    	}else {
    		for(Long userId:users) {
        		OaFlowProcess process = new OaFlowProcess();
        		process.setAddTime(DateUtils.getNowDate());
        		process.setUserId(userId);
        		process.setDocumentId(document.getId());
        		process.setFlowId(document.getFlowId());
        		process.setStepId(step.getId());
        		process.setPrevId(document.getStepId());
        		process.setStatus("1");
        		process.setTitle(step.getTitle());
        		oaFlowProcessMapper.insertOaFlowProcess(process);
        		count ++;
        	}
    	}    	
    	return count;
    }
    

    /**
     * 签收工作流
     * 
     * @param id 工作流步骤ID
     * @return 结果
     */
    @Override
    public int signinOaFlowProcess(Long id) {
    	OaFlowProcess process = oaFlowProcessMapper.selectOaFlowProcessById(id);
    	if(process == null || process.getUserId() != SecurityUtils.getLoginUser().getUser().getUserId()) {
    		throw new CustomException("流程不存在或者您没有权限");
    	}
    	process.setStatus("2");
    	process.setUpdateTime(DateUtils.getNowDate());
    	return oaFlowProcessMapper.updateOaFlowProcess(process);
    }
}
